Load the necessary libraries and source the utility functions.
library(survinng)
library(ggplot2)
library(cowplot)
library(dplyr)
library(tidyr)
library(SurvMetrics)
library(survival)
library(simsurv)
library(survminer)
library(torch)
library(viridis)
library(here)
# Load utility functions
source(here("utils/utils_nn_training.R"))
source(here("utils/utils_plotting.R"))
# Set figure path
fig_path <- here::here("figures_paper")
if (!file.exists(fig_path)) dir.create(fig_path)
fig <- function(x) here::here(fig_path, x)
Simulation setting: - \(10,000\) samples (\(9,500\) for training, \(500\) for testing) - No time-dependent effects - \(X_1 \sim \mathcal{N}(0,1)\) has a positive effect on the hazard -> negative effect on survival - \(X_2 \sim \mathcal{U}(0,1)\) has a stronger negative effect on the hazard -> positive effect on survival - \(X_3 \sim \mathcal{U}(-1,1)\) has no effect
set.seed(42)
# Simulate data
n <- 10000
x <- data.frame(x1 = rnorm(n), x2 = runif(n, 0, 1), x3 = runif(n, -1, 1))
simdat <- simsurv(dist = "weibull", lambdas = 0.1, gammas = 2.5, betas = c(x1 = 1.7, x2 = -2.4),
x = x, maxt = 7)
y <- simdat[, -1]
colnames(y)[1] <- "time"
dat <- cbind(y, x)
# Train/test
idx <- sample(n, 9500)
train <- dat[idx, ]
test <- dat[-idx, ]
ext_deephit <- fit_model("DeepHit", train, test)
ext_coxtime <- fit_model("CoxTime", train, test)
ext_deepsurv <- fit_model("DeepSurv", train, test)
exp_deephit <- survinng::explain(ext_deephit[[1]], data = test)
exp_coxtime <- survinng::explain(ext_coxtime[[1]], data = test)
exp_deepsurv <- survinng::explain(ext_deepsurv[[1]], data = test)
# Define a function to reshape data into a wide matrix format
prepare_matrix <- function(data, id_col = "id", time_col = "time", pred_col = "pred") {
wide_data <- data %>%
pivot_wider(names_from = {{time_col}}, values_from = {{pred_col}})
# Convert the specified column to row names and remove it from the data
wide_data <- as.data.frame(wide_data)
rownames(wide_data) <- wide_data[[id_col]]
wide_data <- wide_data[, -which(names(wide_data) == id_col)]
# Convert to a matrix
as.matrix(wide_data)
}
# Prepare matrices
matrix_coxtime <- prepare_matrix(ext_coxtime$pred)
matrix_deepsurv <- prepare_matrix(ext_deepsurv$pred)
matrix_deephit <- prepare_matrix(ext_deephit$pred)[,-1]
# Define survival object
surv_obj <- Surv(test$time, test$status)
# Define time indices and sampled time
t_interest <- sort(unique(ext_coxtime$pred$time))
num_samples <- 100
indices <- round(seq(1, length(t_interest), length.out = num_samples))
sampled_t <- t_interest[indices]
deephit_t <- sort(unique(ext_deephit$pred$time))[-1]
# Sample matrices
sampled_matrix_coxtime <- matrix_coxtime[, indices]
sampled_matrix_deepsurv <- matrix_deepsurv[, indices]
# Calculate Brier scores in a single step
calculate_brier <- function(matrix, times, surv_obj) {
sapply(1:ncol(matrix), function(i) Brier(surv_obj, pre_sp = matrix[, i], times[i]))
}
metrics_coxtime <- calculate_brier(sampled_matrix_coxtime, sampled_t, surv_obj)
metrics_deepsurv <- calculate_brier(sampled_matrix_deepsurv, sampled_t, surv_obj)
metrics_deephit <- calculate_brier(matrix_deephit, deephit_t, surv_obj)
# Combine results into a single data frame for plotting
combine_results <- function(metrics, times, model_name) {
data.frame(time = times, BS = metrics, model = model_name)
}
data_coxtime <- combine_results(metrics_coxtime, sampled_t, "CoxTime")
data_deepsurv <- combine_results(metrics_deepsurv, sampled_t, "DeepSurv")
data_deephit <- combine_results(metrics_deephit, deephit_t, "DeepHit")
data_BS <- rbind(data_coxtime, data_deepsurv, data_deephit)
# Plot Brier scores
colorblind_palette <- c("CoxTime" = "#E69F00", "DeepSurv" = "#56B4E9", "DeepHit" = "#009E73")
brier_plot_tid <- ggplot() +
geom_line(data = data_BS, aes(x = time, y = BS, color = model, linetype = model)) +
geom_rug(data = test, aes(x = time), sides = "bl", linewidth = 0.5, alpha = 0.5) +
geom_hline(yintercept = 0) +
scale_color_manual(values = colorblind_palette) + # Apply custom colors
scale_linetype_manual(values = c("CoxTime" = "solid", "DeepSurv" = "dashed", "DeepHit" = "dotted")) +
labs(title = "", x = "Time", y = "Brier Score", color = NULL, linetype = NULL) +
theme_minimal(base_size = 17) +
theme(legend.position = "bottom")
brier_plot_tid
# Save plot
ggsave(fig("sim_tid_brier_plot.pdf"), plot = brier_plot_tid, width = 7, height = 5)
# Calculate C-index and IBS for each model
calculate_cindex <- function(matrix, surv_obj, index) {
Cindex(surv_obj, predicted = matrix[, index])
}
calculate_ibs <- function(matrix, times, surv_obj) {
IBS(surv_obj, sp_matrix = matrix, times)
}
C_coxtime <- calculate_cindex(sampled_matrix_coxtime, surv_obj, 50)
C_deepsurv <- calculate_cindex(sampled_matrix_deepsurv, surv_obj, 50)
C_deephit <- calculate_cindex(matrix_deephit, surv_obj, 15)
IBS_coxtime <- calculate_ibs(sampled_matrix_coxtime, sampled_t, surv_obj)
IBS_deepsurv <- calculate_ibs(sampled_matrix_deepsurv, sampled_t, surv_obj)
IBS_deephit <- calculate_ibs(matrix_deephit[,-1], deephit_t[-1], surv_obj)
# Display results
res <- data.frame(
model = c("CoxTime", "DeepSurv", "DeepHit"),
C_index = c(C_coxtime, C_deepsurv, C_deephit),
IBS = c(IBS_coxtime, IBS_deepsurv, IBS_deephit)
)
saveRDS(res, fig("sim_tid_performance.rds"))
res
#> model C_index IBS
#> 1 CoxTime 0.809372 0.099053
#> 2 DeepSurv 0.809121 0.099031
#> 3 DeepHit 0.808829 0.141614
# Print instances of interest
tid_ids <- c(13, 387)
print(test[tid_ids, ])
#> time status x1 x2 x3
#> 343 2.6653596 1 -0.434617 0.1162303 -0.08053765
#> 7906 0.9577924 1 2.454611 0.2462072 -0.04249294
# Compute Vanilla Gradient
grad_cox <- surv_grad(exp_coxtime, target = "survival", instance = tid_ids)
grad_deephit <- surv_grad(exp_deephit, target = "survival", instance = tid_ids)
grad_deepsurv <- surv_grad(exp_deepsurv, target = "survival", instance = tid_ids)
# Plot survival predictions
surv_plot <- cowplot::plot_grid(
plot_surv_pred(grad_cox),
plot_surv_pred(grad_deephit),
plot_surv_pred(grad_deepsurv),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"),
label_x = 0.03,
label_size = 14)
surv_plot
# Save plot
ggsave(fig("sim_tid_surv_plot.pdf"), plot = surv_plot, width = 8, height = 14)
# Plot attributions
grad_plot <- cowplot::plot_grid(
plot_attribution(grad_cox, label = "Grad(t)") ,
plot_attribution(grad_deephit, label = "Grad(t)"),
plot_attribution(grad_deepsurv, label = "Grad(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
grad_plot
# Save plot
ggsave(fig("sim_tid_grad_plot.pdf"), plot = grad_plot, width = 10, height = 14)
# Plot normalized attributions
grad_plot_norm <- cowplot::plot_grid(
plot_attribution(grad_cox, normalize = TRUE, label = "Grad(t)"),
plot_attribution(grad_deephit, normalize = TRUE, label = "Grad(t)"),
plot_attribution(grad_deepsurv, normalize = TRUE, label = "Grad(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
grad_plot_norm
# Save plot
ggsave(fig("sim_tid_grad_plot_norm.pdf"), plot = grad_plot_norm, width = 10, height = 14)
# Compute SmoothGrad
sg_cox <- surv_smoothgrad(exp_coxtime, target = "survival", instance = tid_ids, n = 50, noise_level = 0.1)
sg_deephit <- surv_smoothgrad(exp_deephit, target = "survival", instance = tid_ids, n = 50, noise_level = 0.1)
sg_deepsurv <- surv_smoothgrad(exp_deepsurv, target = "survival", instance = tid_ids, n = 50, noise_level = 0.1)
# Plot attributions
smoothgrad_plot <- cowplot::plot_grid(
plot_attribution(sg_cox, label = "SG(t)"),
plot_attribution(sg_deephit, label = "SG(t)"),
plot_attribution(sg_deepsurv, label = "SG(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
smoothgrad_plot
# Save plot
ggsave(fig("sim_tid_smoothgrad_plot.pdf"), plot = smoothgrad_plot, width = 10, height = 14)
# Plot normalized attributions
smoothgrad_plot_norm <- cowplot::plot_grid(
plot_attribution(grad_cox, normalize = TRUE, label = "SG(t)"),
plot_attribution(grad_deephit, normalize = TRUE, label = "SG(t)"),
plot_attribution(grad_deepsurv, normalize = TRUE, label = "SG(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
smoothgrad_plot_norm
# Save plot
ggsave(fig("sim_tid_smoothgrad_plot_norm.pdf"), plot = smoothgrad_plot_norm, width = 10, height = 14)
# Compute GradientxInput
gradin_cox <- surv_grad(exp_coxtime, instance = tid_ids, times_input = TRUE)
gradin_deephit <- surv_grad(exp_deephit, instance = tid_ids, times_input = TRUE)
gradin_deepsurv <- surv_grad(exp_deepsurv, instance = tid_ids, times_input = TRUE)
# Plot attributions
gradin_plot <- cowplot::plot_grid(
plot_attribution(gradin_cox, label = "GxI(t)"),
plot_attribution(gradin_deephit, label = "GxI(t)"),
plot_attribution(gradin_deepsurv, label = "GxI(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
gradin_plot
# Save plot
ggsave(fig("sim_tid_gradin_plot.pdf"), plot = gradin_plot, width = 10, height = 14)
# Plot attributions
grad_gradin_plot <- cowplot::plot_grid(
plot_attribution(grad_deepsurv, label = "Grad(t)") ,
plot_attribution(gradin_deepsurv, label = "GxI(t)"),
nrow = 2, labels = c("DeepSurv", "DeepSurv"))
grad_gradin_plot
# Save plot
ggsave(fig("sim_tid_grad_gradin_plot.pdf"), plot = grad_gradin_plot, width = 10, height = 9)
# Plot attributions
gradin_plot_norm <- cowplot::plot_grid(
plot_attribution(gradin_cox, normalize = TRUE, label = "GxI(t)"),
plot_attribution(gradin_deephit, normalize = TRUE, label = "GxI(t)"),
plot_attribution(gradin_deepsurv, normalize = TRUE, label = "GxI(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
gradin_plot_norm
# Save plot
ggsave(fig("sim_tid_gradin_plot_norm.pdf"), plot = gradin_plot_norm, width = 10, height = 14)
# Compute SmoothGradxInput
sgin_cox <- surv_smoothgrad(exp_coxtime, instance = tid_ids, n = 50, noise_level = 0.3,
times_input = TRUE)
sgin_deephit <- surv_smoothgrad(exp_deephit, instance = tid_ids, n = 50, noise_level = 0.3,
times_input = TRUE)
sgin_deepsurv <- surv_smoothgrad(exp_deepsurv, instance = tid_ids, n = 50, noise_level = 0.3,
times_input = TRUE)
# Plot attributions
smoothgradin_plot <- cowplot::plot_grid(
plot_attribution(sgin_cox, label = "SGxI(t)"),
plot_attribution(sgin_deephit, label = "SGxI(t)"),
plot_attribution(sgin_deepsurv, label = "SGxI(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
smoothgradin_plot
# Save plot
ggsave(fig("sim_tid_smoothgradin_plot.pdf"), plot = smoothgradin_plot, width = 10, height = 14)
# Plot attributions
smoothgradin_plot_norm <- cowplot::plot_grid(
plot_attribution(sgin_cox, normalize = TRUE, label = "SGxI(t)"),
plot_attribution(sgin_deephit, normalize = TRUE, label = "SGxI(t)"),
plot_attribution(sgin_deepsurv, normalize = TRUE, label = "SGxI(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
smoothgradin_plot_norm
# Save plot
ggsave(fig("sim_tid_smoothgradin_plot_norm.pdf"), plot = smoothgradin_plot_norm, width = 10, height = 14)
# Compute IntegratedGradient with 0 baseline
x_ref <- matrix(c(0,0,0), nrow = 1)
ig0_cox <- surv_intgrad(exp_coxtime, instance = tid_ids, n = 50, x_ref = x_ref)
ig0_deephit <- surv_intgrad(exp_deephit, instance = tid_ids, n = 50, x_ref = x_ref)
ig0_deepsurv <- surv_intgrad(exp_deepsurv, instance = tid_ids, n = 50, x_ref = x_ref)
# Plot attributions
intgrad0_plot <- cowplot::plot_grid(
plot_attribution(ig0_cox, label = "IntGrad(t)"),
plot_attribution(ig0_deephit, label = "IntGrad(t)"),
plot_attribution(ig0_deepsurv, label = "IntGrad(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
intgrad0_plot
# Save plot
ggsave(fig("sim_tid_intgrad0_plot.pdf"), plot = intgrad0_plot, width = 10, height = 14)
# Plot attributions
intgrad0_plot_comp <- cowplot::plot_grid(
plot_attribution(ig0_cox, add_comp = TRUE, label = "IntGrad(t)"),
plot_attribution(ig0_deephit, add_comp = TRUE, label = "IntGrad(t)"),
plot_attribution(ig0_deepsurv, add_comp = TRUE, label = "IntGrad(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
intgrad0_plot_comp
# Save plot
ggsave(fig("sim_tid_intgrad0_plot_comp.pdf"), plot = intgrad0_plot_comp, width = 10, height = 14)
# Plot contributions
intgrad0_plot_contr <- cowplot::plot_grid(
plot_contribution(ig0_cox, label = "IntGrad(t)"),
plot_contribution(ig0_deephit, label = "IntGrad(t)"),
plot_contribution(ig0_deepsurv, label = "IntGrad(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
intgrad0_plot_contr
# Save plot
ggsave(fig("sim_tid_intgrad0_plot_contr.pdf"), plot = intgrad0_plot_contr, width = 10, height = 14)
# Plot force
intgrad0_plot_force <- cowplot::plot_grid(
plot_force(ig0_cox, upper_distance = 0.04, lower_distance = 0.04, label = "IntGrad(t)"),
plot_force(ig0_deephit, upper_distance = 0.02, lower_distance = 0, label = "IntGrad(t)"),
plot_force(ig0_deepsurv, upper_distance = 0.04, lower_distance = 0.04, label = "IntGrad(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
intgrad0_plot_force
# Save plot
ggsave(fig("sim_tid_intgrad0_plot_force.pdf"), plot = intgrad0_plot_force, width = 10, height = 14)
# Compute IntegratedGradient with mean baseline
x_ref <- NULL # default: feature-wise mean
igm_cox <- surv_intgrad(exp_coxtime, instance = tid_ids, n = 50, x_ref = x_ref)
igm_deephit <- surv_intgrad(exp_deephit, instance = tid_ids, n = 50, x_ref = x_ref)
igm_deepsurv <- surv_intgrad(exp_deepsurv, instance = tid_ids, n = 50, x_ref = x_ref)
# Plot attributions
intgradmean_plot <- cowplot::plot_grid(
plot_attribution(igm_cox, label = "IntGrad(t)"),
plot_attribution(igm_deephit, label = "IntGrad(t)"),
plot_attribution(igm_deepsurv, label = "IntGrad(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
intgradmean_plot
# Save plot
ggsave(fig("sim_tid_intgradmean_plot.pdf"), plot = intgradmean_plot, width = 10, height = 14)
# Plot attributions
intgradmean_plot_comp <- cowplot::plot_grid(
plot_attribution(igm_cox, add_comp = TRUE, label = "IntGrad(t)"),
plot_attribution(igm_deephit, add_comp = TRUE, label = "IntGrad(t)"),
plot_attribution(igm_deepsurv, add_comp = TRUE, label = "IntGrad(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
intgradmean_plot_comp
# Save plot
ggsave(fig("sim_tid_intgradmean_plot_comp.pdf"), plot = intgradmean_plot_comp, width = 10, height = 14)
# Plot contributions
intgradm_plot_contr <- cowplot::plot_grid(
plot_contribution(igm_cox, label = "IntGrad(t)"),
plot_contribution(igm_deephit, label = "IntGrad(t)"),
plot_contribution(igm_deepsurv, label = "IntGrad(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
intgradm_plot_contr
# Save plot
ggsave(fig("sim_tid_intgradm_plot_contr.pdf"), plot = intgradm_plot_contr, width = 10, height = 14)
# Plot force
intgradm_plot_force <- cowplot::plot_grid(
plot_force(igm_cox, upper_distance = 0, lower_distance = 0, label = "IntGrad(t)"),
plot_force(igm_deephit, upper_distance = 0, lower_distance = 0, label = "IntGrad(t)"),
plot_force(igm_deepsurv, upper_distance = 0, lower_distance = 0, label = "IntGrad(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
intgradm_plot_force
# Save plot
ggsave(fig("sim_tid_intgradm_plot_force.pdf"), plot = intgradm_plot_force, width = 10, height = 14)
# Compute GradShap
gshap_cox <- surv_gradSHAP(exp_coxtime, instance = tid_ids, n = 50, num_samples = 100)
gshap_deephit <- surv_gradSHAP(exp_deephit, instance = tid_ids, n = 50, num_samples = 100)
gshap_deepsurv <- surv_gradSHAP(exp_deepsurv, instance = tid_ids, n = 50, num_samples = 100)
# Plot attributions
gshap_plot <- cowplot::plot_grid(
plot_attribution(gshap_cox, label = "GradSHAP(t)"),
plot_attribution(gshap_deephit, label = "GradSHAP(t)"),
plot_attribution(gshap_deepsurv, label = "GradSHAP(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
gshap_plot
# Save plot
ggsave(fig("sim_tid_gshap_plot.pdf"), plot = gshap_plot, width = 10, height = 14)
# Plot attributions
gshap_plot_comp <- cowplot::plot_grid(
plot_attribution(gshap_cox, add_comp = TRUE, label = "GradSHAP(t)"),
plot_attribution(gshap_deephit, add_comp = TRUE, label = "GradSHAP(t)"),
plot_attribution(gshap_deepsurv, add_comp = TRUE, label = "GradSHAP(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
gshap_plot_comp
# Save plot
ggsave(fig("sim_tid_gshap_plot_comp.pdf"), plot = gshap_plot_comp, width = 10, height = 14)
# Plot contributions %
gshap_plot_contr <- cowplot::plot_grid(
plot_contribution(gshap_cox, label = "GradSHAP(t)"),
plot_contribution(gshap_deephit, label = "GradSHAP(t)"),
plot_contribution(gshap_deepsurv, label = "GradSHAP(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
gshap_plot_contr
# Save plot
ggsave(fig("sim_tid_gshap_plot_contr.pdf"), plot = gshap_plot_contr, width = 10, height = 14)
# Plot force
gshap_plot_force <- cowplot::plot_grid(
plot_force(gshap_cox, upper_distance = 0, lower_distance = 0, lower_distance_x1 = 0.05, label = "GradSHAP(t)"),
plot_force(gshap_deephit, upper_distance = 0, lower_distance = 0, lower_distance_x1 = 0.02, label = "GradSHAP(t)"),
plot_force(gshap_deepsurv, upper_distance = 0, lower_distance = 0, lower_distance_x1 = 0.04, label = "GradSHAP(t)"),
nrow = 3, labels = c("CoxTime", "DeepHit", "DeepSurv"))
gshap_plot_force
# Save plot
ggsave(fig("sim_tid_gshap_plot_force.pdf"), plot = gshap_plot_force, width = 10, height = 14)
sessionInfo()
#> R version 4.4.3 (2025-02-28)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 22.04.5 LTS
#>
#> Matrix products: default
#> BLAS: /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0
#> LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] batchtools_0.9.17 data.table_1.16.4 here_1.0.1
#> [4] callr_3.7.6 reticulate_1.40.0 torch_0.14.2
#> [7] tidyr_1.3.1 dplyr_1.1.4 viridis_0.6.5
#> [10] viridisLite_0.4.2 cowplot_1.1.3 survivalmodels_0.1.191
#> [13] survex_1.2.0 survinng_0.1.0 SurvMetrics_0.5.0
#> [16] survminer_0.5.0 ggpubr_0.6.0 ggplot2_3.5.2
#> [19] survival_3.8-3 simsurv_1.0.0 devtools_2.4.5
#> [22] usethis_3.1.0 rmarkdown_2.29
#>
#> loaded via a namespace (and not attached):
#> [1] RColorBrewer_1.1-3 jsonlite_2.0.0 magrittr_2.0.3
#> [4] farver_2.1.2 DALEX_2.4.3 fs_1.6.5
#> [7] ragg_1.3.3 vctrs_0.6.5 memoise_2.0.1
#> [10] rstatix_0.7.2 htmltools_0.5.8.1 progress_1.2.3
#> [13] broom_1.0.7 Formula_1.2-5 sass_0.4.9
#> [16] parallelly_1.41.0 bslib_0.8.0 htmlwidgets_1.6.4
#> [19] zoo_1.8-12 cachem_1.1.0 mime_0.12
#> [22] lifecycle_1.0.4 iterators_1.0.14 pkgconfig_2.0.3
#> [25] Matrix_1.7-2 R6_2.6.1 fastmap_1.2.0
#> [28] future_1.34.0 shiny_1.10.0 digest_0.6.37
#> [31] numDeriv_2016.8-1.1 patchwork_1.3.0 ps_1.9.1
#> [34] rprojroot_2.0.4 pkgload_1.4.0 textshaping_1.0.0
#> [37] base64url_1.4 labeling_0.4.3 km.ci_0.5-6
#> [40] abind_1.4-8 compiler_4.4.3 remotes_2.5.0
#> [43] bit64_4.6.0-1 withr_3.0.2 brew_1.0-10
#> [46] backports_1.5.0 carData_3.0-5 pkgbuild_1.4.6
#> [49] ggsignif_0.6.4 MASS_7.3-65 lava_1.8.1
#> [52] rappdirs_0.3.3 sessioninfo_1.2.2 tools_4.4.3
#> [55] httpuv_1.6.15 future.apply_1.11.3 glue_1.8.0
#> [58] DiagrammeR_1.0.11 promises_1.3.2 grid_4.4.3
#> [61] checkmate_2.3.2 generics_0.1.4 gtable_0.3.6
#> [64] KMsurv_0.1-5 hms_1.1.3 car_3.1-3
#> [67] foreach_1.5.2 pillar_1.10.2 later_1.4.1
#> [70] splines_4.4.3 lattice_0.22-5 bit_4.6.0
#> [73] tidyselect_1.2.1 coro_1.1.0 miniUI_0.1.1.1
#> [76] knitr_1.49 gridExtra_2.3 xfun_0.50
#> [79] visNetwork_2.1.2 stringi_1.8.4 yaml_2.3.10
#> [82] pec_2023.04.12 evaluate_1.0.3 codetools_0.2-19
#> [85] data.tree_1.1.0 tibble_3.2.1 cli_3.6.5
#> [88] xtable_1.8-4 randomForestSRC_3.3.3 systemfonts_1.2.1
#> [91] processx_3.8.6 jquerylib_0.1.4 survMisc_0.5.6
#> [94] Rcpp_1.0.14 globals_0.16.3 png_0.1-8
#> [97] parallel_4.4.3 ellipsis_0.3.2 prettyunits_1.2.0
#> [100] profvis_0.4.0 urlchecker_1.0.1 listenv_0.9.1
#> [103] timereg_2.0.6 scales_1.4.0 prodlim_2024.06.25
#> [106] purrr_1.0.2 crayon_1.5.3 rlang_1.1.6